// File: jmcomic-core/src/main/java/dev/jukomu/jmcomic/entity/JmAlbumDetail.java
package dev.jukomu.jmcomic.entity;

import dev.jukomu.jmcomic.config.JmModuleConfig;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 对应Python的JmAlbumDetail，表示禁漫的本子详情。
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class JmAlbumDetail extends DetailEntity<JmPhotoDetail> implements Downloadable {

    // --- Setters for other properties if needed for external modification ---
    @Getter
    @Setter
    private String albumId;
    @Getter
    @Setter
    private String scrambleId; // 本子解密ID
    @Getter
    @Setter
    private String name; // 本子名称/标题
    @Getter
    @Setter
    private int pageCount; // 总页数
    @Getter
    @Setter
    private String pubDate; // 发布日期
    @Getter
    @Setter
    private String updateDate; // 更新日期

    @Getter
    @Setter
    private String likes; // 例如 "1K" 喜欢数
    @Getter
    @Setter
    private String views; // 例如 "40K" 观看数
    @Getter
    @Setter
    private int commentCount; // 评论数
    @Getter
    @Setter
    private List<String> works; // 作品列表
    @Getter
    @Setter
    private List<String> actors; // 登场人物列表
    @Getter
    @Setter
    private List<String> authors; // 作者列表
    @Getter
    @Setter
    private List<String> tags; // 标签列表

    @Getter
    private List<Triple<String, String, String>> episodeList; // 章节列表 (photo_id, photo_index, photo_title)
    @Getter
    @Setter
    private List<Map<String, Object>> relatedList; // 相关本子列表 (Map representing simple album info)

    // Downloadable接口的字段
    private String savePath;
    private boolean exists;
    private boolean skip;

    // 缓存JmPhotoDetail实例
    private transient Map<Integer, JmPhotoDetail> photoDetailCache = new ConcurrentHashMap<>();


    /**
     * 构造函数。
     *
     * @param albumId      本子ID
     * @param scrambleId   本子解密ID
     * @param name         本子名称
     * @param episodeList  章节列表 (List of Triple<photoId, photoIndex, photoTitle>)
     * @param pageCount    总页数
     * @param pubDate      发布日期
     * @param updateDate   更新日期
     * @param likes        喜欢数
     * @param views        观看数
     * @param commentCount 评论数
     * @param works        作品列表
     * @param actors       登场人物列表
     * @param authors      作者列表
     * @param tags         标签列表
     * @param relatedList  相关本子列表
     */
    public JmAlbumDetail(String albumId, String scrambleId, String name, List<Triple<String, String, String>> episodeList, int pageCount, String pubDate, String updateDate, String likes, String views, int commentCount, List<String> works, List<String> actors, List<String> authors, List<String> tags, List<Map<String, Object>> relatedList) {
        this.albumId = albumId;
        this.scrambleId = scrambleId != null ? scrambleId : "0";
        this.name = name != null ? name.trim() : "";
        this.pageCount = pageCount;
        this.pubDate = pubDate != null ? pubDate : "";
        this.updateDate = updateDate != null ? updateDate : "";
        this.likes = likes != null ? likes : "";
        this.views = views != null ? views : "";
        this.commentCount = commentCount;
        this.works = works != null ? Collections.unmodifiableList(works) : Collections.emptyList();
        this.actors = actors != null ? Collections.unmodifiableList(actors) : Collections.emptyList();
        this.authors = authors != null ? Collections.unmodifiableList(authors) : Collections.emptyList();
        this.tags = tags != null ? Collections.unmodifiableList(tags) : Collections.emptyList();
        this.relatedList = relatedList != null ? Collections.unmodifiableList(relatedList) : Collections.emptyList();

        // 构造函数不再处理空episodeList，直接接收并去重
        if (episodeList != null || !episodeList.isEmpty()) {
            this.episodeList = Collections.unmodifiableList(distinctEpisode(episodeList));
        } else {
            this.episodeList = Collections.singletonList(Triple.of(this.albumId, "1", this.name));
        }
    }

    /**
     * 默认构造函数（用于JSON反序列化和反射）。
     */
    public JmAlbumDetail() {
        // 初始化列表字段以避免NullPointerException
        this.episodeList = Collections.emptyList();
        this.works = Collections.emptyList();
        this.actors = Collections.emptyList();
        this.authors = Collections.emptyList();
        this.tags = Collections.emptyList();
        this.relatedList = Collections.emptyList();
    }

    /**
     * 去除重复章节，并按章节索引排序。
     *
     * @param episodeList 原始章节列表 (Triple<photoId, photoIndex, photoTitle>)
     * @return 去重排序后的章节列表
     */
    private List<Triple<String, String, String>> distinctEpisode(List<Triple<String, String, String>> episodeList) {
        // 按photo_index排序
        List<Triple<String, String, String>> sortedList = episodeList.stream()
                .sorted(Comparator.comparingInt(e -> Integer.parseInt(e.getSecond())))
                .collect(Collectors.toList());

        // 去重
        List<Triple<String, String, String>> distinctList = new java.util.ArrayList<>();
        if (!sortedList.isEmpty()) {
            distinctList.add(sortedList.get(0));
            for (int i = 1; i < sortedList.size(); i++) {
                // 如果当前章节的索引与上一个不同，则添加
                if (!sortedList.get(i).getSecond().equals(distinctList.get(distinctList.size() - 1).getSecond())) {
                    distinctList.add(sortedList.get(i));
                }
            }
        }
        return distinctList;
    }

    /**
     * 获取本子的ID。
     *
     * @return 本子ID字符串
     */
    @Override
    public String getId() {
        return albumId;
    }

    /**
     * 获取本子的标题。
     *
     * @return 本子标题字符串
     */
    @Override
    public String getTitle() {
        return name;
    }

    /**
     * 获取本子的主要作者。
     * 如果有多个作者，返回第一个；否则返回默认作者。
     *
     * @return 作者字符串
     */
    @Override
    public String getAuthor() {
        if (!authors.isEmpty()) {
            return authors.get(0);
        }
        return JmModuleConfig.DEFAULT_AUTHOR;
    }

    /**
     * 创建指定索引的章节详情实例。
     *
     * @param index 章节索引（从0开始）
     * @return JmPhotoDetail实例
     * @throws IndexOutOfBoundsException 如果索引超出范围
     */
    @Override
    public JmPhotoDetail get(int index) {
        if (index < 0 || index >= episodeList.size()) {
            throw new IndexOutOfBoundsException(String.format("Photo index out of range for album-%s: %d >= %d", albumId, index, episodeList.size()));
        }

        // 实现lru_cache，缓存JmPhotoDetail实例
        return photoDetailCache.computeIfAbsent(index, i -> {
            Triple<String, String, String> episode = episodeList.get(i);
            // pid, pindex, pname
            return (JmPhotoDetail) JmModuleConfig.getPhotoClass().cast(
                    new JmPhotoDetail(
                            episode.getFirst(), // photo_id
                            scrambleId, // 使用本子的解密ID
                            episode.getThird(), // photo_title
                            Integer.parseInt(albumId), // series_id (本子ID)
                            Integer.parseInt(episode.getSecond()), // sort (章节索引)
                            this // fromAlbum
                    )
            );
        });
    }

    /**
     * 获取本子中章节的数量。
     *
     * @return 章节数量
     */
    @Override
    public int size() {
        // 再次构造章节列表
        if (episodeList.isEmpty()) {
            this.episodeList = Collections.singletonList(Triple.of(this.albumId, "1", this.name));
        }
        return episodeList.size();
    }

    @Override
    public boolean isAlbum() {
        return true;
    }

    // --- Getters for fields ---

    // --- Setters for Downloadable interface ---
    @Override
    public String getSavePath() {
        return savePath;
    }

    @Override
    public void setSavePath(String savePath) {
        this.savePath = savePath;
    }

    @Override
    public boolean isExists() {
        return exists;
    }

    @Override
    public void setExists(boolean exists) {
        this.exists = exists;
    }

    @Override
    public boolean isSkip() {
        return skip;
    }

    @Override
    public void setSkip(boolean skip) {
        this.skip = skip;
    }

    public void setEpisodeList(List<Triple<String, String, String>> episodeList) {
        this.episodeList = Collections.unmodifiableList(distinctEpisode(episodeList));
    }
}